import { BadRequestException, Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
// entities
import { UserEntity } from './entities';
import { bcryptCompare, bcryptHash } from '@app/utils';
import { plainToInstance } from 'class-transformer';
import { AuthUserInfoDto } from './dtos';

@Injectable()
export class UserService {
  private readonly logger = new Logger(UserService.name);

  constructor(
    @InjectRepository(UserEntity)
    private readonly userRepository: Repository<UserEntity>,
  ) {}

  /**
   * Jwt策略Local校验用户数据
   * @param {string} username 用户名称
   * @param {string} password 用户密码
   */
  async validateUser(username: string, password: string): Promise<UserEntity> {
    this.logger.debug('username:' + username);
    this.logger.debug('password:' + password);
    // 查找用户
    const user = await this.userRepository.findOneBy({
      username,
    });
    // 不存在提示
    if (!user) {
      throw new BadRequestException('用户名不正确！');
    }
    this.logger.debug('bcryptHash:' + bcryptHash(password));
    // 密码校验
    if (bcryptCompare(password, user.password)) {
      // 状态检查
      if (user.status !== 1) {
        throw new BadRequestException('当前用户状态不可用！');
      }
      return user;
    }
    throw new BadRequestException('用户密码校验失败！');
  }


  /**
   * 通过id取得信息
   * @param id
   */
  async getUserById(id: number): Promise<UserEntity | null> {
    return await this.userRepository.findOneByOrFail({
      id,
    });
  }

  /**
   * 取得登录用户信息
   * @param user
   */
  async getUserWithAuthorities(user: any) {
    const userInfo = await this.getUserById(user.id);
    // 加载角色权限
    const outUserInfo = plainToInstance(AuthUserInfoDto, userInfo, {
      excludeExtraneousValues: true,
    });
    // 权限集
    let authorities: any[] = []; // await this.menuService.getMenuAll();
    // 超管直接返回所有
    let roles: any[] = []; // await this.roleService.getRoleAll();

    // 设置值
    outUserInfo.roles = roles;
    outUserInfo.authorities = authorities;

    return outUserInfo;
  }
}
